﻿using System;
using System.Diagnostics;


///////////////////////////////////////////////////////////////////////////////


// Since this class doesn't explicitly define a type constructor,
// C# marks the type definition with BeforeFieldInit in the metadata.
internal sealed class BeforeFieldInit {
	public static Int32 s_x = 123;
}

// Since this class does explicitly define a type constructor,
// C# doesn't mark the type definition with BeforeFieldInit in the metadata.
internal sealed class Precise {
	public static Int32 s_x;
	static Precise() { s_x = 123; }
}


///////////////////////////////////////////////////////////////////////////////


public sealed class Program {
	public static void Main() {
		const Int32 iterations = 1000 * 1000 * 1000;
		PerfTest1(iterations);
		PerfTest2(iterations);
	}


	// When this method is JIT compiled, the type constructors for
	// the BeforeFieldInit and Precise classes HAVE NOT executed yet 
	// and therefore, calls to these constructors are embedded in 
	// this method's code making it run slower
	private static void PerfTest1(Int32 iterations) {
		Stopwatch sw = Stopwatch.StartNew();
		for (Int32 x = 0; x < iterations; x++) {
			// The JIT compiler hoists the code to call BeforeFieldInit's 
			// type constructor so that it executes before the loop starts
			BeforeFieldInit.s_x = 1;
		}
		Console.WriteLine("PerfTest1: {0} BeforeFieldInit", sw.Elapsed);

		sw = Stopwatch.StartNew();
		for (Int32 x = 0; x < iterations; x++) {
			// The JIT compiler emits the code to call Precise's 
			// type constructor here so that it checks whether it
			// has to call the constructor with each loop iteration
			Precise.s_x = 1;
		}
		Console.WriteLine("PerfTest1: {0} Precise", sw.Elapsed);
	}

	// When this method is JIT compiled, the type constructors for
	// the BeforeFieldInit and Precise classes HAVE executed 
	// and therefore, calls to these constructors are NOT embedded 
	// in this method's code making it run faster
	private static void PerfTest2(Int32 iterations) {
		Stopwatch sw = Stopwatch.StartNew();
		for (Int32 x = 0; x < iterations; x++) {
			BeforeFieldInit.s_x = 1;
		}
		Console.WriteLine("PerfTest2: {0} BeforeFieldInit", sw.Elapsed);

		sw = Stopwatch.StartNew();
		for (Int32 x = 0; x < iterations; x++) {
			Precise.s_x = 1;
		}
		Console.WriteLine("PerfTest2: {0} Precise", sw.Elapsed);
	}
}


////////////////////////////// End of File ////////////////////////////////////
